package airdata

import (
	"context"
	"fmt"
	"iot-base/auth/svc"
	"iot-base/common/cache"
	"time"
)

var devStr = map[string][]string{
	"m_co":   {"pmt_v", "canbi_v", "press", "flow", "temp", "xg_temp"},
	"m_so2":  {"pmt_v", "canbi_v", "power", "press", "flow", "temp", "boxtemp", "pmt_hvdis", "xiandeng_hv"},
	"m_nox":  {"pmt_fileter_nov", "pmt_fileter_noxv", "power", "press", "flow", "temp", "boxtemp", "mulu_temp", "canbi_v", "cell_press", "sample_flow", "pmt_hvdis"},
	"m_o3":   {"pmt_v", "canbi_v", "power", "press", "flow", "temp", "boxtemp", "uvtemp"},
	"m_pm25": {"power", "apress", "sflow", "heatertemp", "boxtemp", "dpress", "ppress", "cumulative_mass", "ambient_temp", "humidity", "oflow", "temp"},
	"m_pm10": {"power", "apress", "sflow", "heatertemp", "boxtemp", "dpress", "ppress", "cumulative_mass", "ambient_temp", "humidity", "oflow", "temp"},
}
var modelDevStr = []string{"m_co", "m_nox", "m_o3", "m_pm25", "m_pm10", "m_so2"}

//键值存储当前项目co,no,no2,nox等,值为当前采集的数据
type chanDevDt chan map[string][]AirDevStatus

type AirDevStatus struct {
	Name      string
	Brand     string //@仪器的品牌,型号 例 XH,XH2309
	Value     float64
	Max       float64
	Min       float64
	Status    int //@ 状态 0 未知 1 正常  2 校准  3 开机 4 中断恢复 5 诊断 6 零点校准 7 跨度校准 8 有效数据不足
	CreatTime time.Time
	Unit      string
}

func get5minuteDev() {
	hisdata, err := svc.Dao.THisData.QueryHisByModelTimeStyle(modelDevStr, "5minute", time.Now().Add(-11*time.Minute))
	if err != nil {
		return
	}
	var result = make(map[string][]AirDevStatus)
	for _, v := range hisdata {
		ok, item := cache.GetModelProperty(v.ModelID, v.Field, "")
		var (
			name string
			max  float64
			min  float64
		)
		if ok {
			name = item.Name
			max = item.Max
			min = item.Min
		} else {
			fmt.Println("property is not exist", v.ModelID, v.Field)
		}
		var brand string
		thingInfo, err := cache.GetThing(v.ThingID)
		if err == nil {
			brand = thingInfo.GetThingParam("spec", "")
		}
		var airDevStatus = AirDevStatus{
			Name:      name,
			Max:       max,
			Min:       min,
			Brand:     brand,
			Value:     v.Value,
			Status:    v.Status,
			CreatTime: v.PickTime,
			Unit:      item.UnitName,
		}
		if v.Total < 9 {
			airDevStatus.Status = 8
		}
		propertys, ok := devStr[v.ModelID]
		if !ok {
			fmt.Println("no this dev")
		}
		switch v.ModelID {
		case "m_co":
			if _, ok := result["co"]; !ok {
				result["co"] = []AirDevStatus{}
			}
			for _, p := range propertys {
				if v.Field == p {
					m, ok := result["co"]
					if ok {
						result["co"] = append(m, airDevStatus)
					}
				}
			}
		case "m_nox":
			if _, ok := result["no"]; !ok {
				result["no"] = []AirDevStatus{}
			}
			if _, ok := result["no2"]; !ok {
				result["no2"] = []AirDevStatus{}
			}
			if _, ok := result["nox"]; !ok {
				result["nox"] = []AirDevStatus{}
			}
			for _, p := range propertys {
				if v.Field == p {
					no, ok := result["no"]
					no2, ok := result["no2"]
					nox, ok := result["nox"]
					if ok {
						result["no"] = append(no, airDevStatus)
						result["no2"] = append(no2, airDevStatus)
						result["nox"] = append(nox, airDevStatus)
					}
				}
			}
		case "m_so2":
			if _, ok := result["so2"]; !ok {
				result["so2"] = []AirDevStatus{}
			}
			for _, p := range propertys {
				if v.Field == p {
					m, ok := result["so2"]
					if ok {
						result["so2"] = append(m, airDevStatus)
					}
				}
			}
		case "m_o3":
			if _, ok := result["o3"]; !ok {
				result["o3"] = []AirDevStatus{}
			}
			for _, p := range propertys {
				if v.Field == p {
					m, ok := result["o3"]
					if ok {
						result["o3"] = append(m, airDevStatus)
					}
				}
			}
		case "m_pm25":
			if _, ok := result["pm2.5"]; !ok {
				result["pm2.5"] = []AirDevStatus{}
			}
			for _, p := range propertys {
				if v.Field == p {
					m, ok := result["pm2.5"]
					if ok {
						result["pm2.5"] = append(m, airDevStatus)
					}
				}
			}
		case "m_pm10":
			if _, ok := result["pm10"]; !ok {
				result["pm10"] = []AirDevStatus{}
			}
			for _, p := range propertys {
				if v.Field == p {
					m, ok := result["pm10"]
					if ok {
						result["pm10"] = append(m, airDevStatus)
					}
				}
			}
		}
	}
	for _, v := range consumer5minuteDev {
		v <- result
	}
}

func getHourDev() {
	hisdata, err := svc.Dao.THisData.QueryHisByModelTimeStyle(modelDevStr, "hour", time.Now().Add(-1*time.Hour-1*time.Minute))
	if err != nil {
		return
	}
	var result = make(map[string][]AirDevStatus)
	for _, v := range hisdata {
		ok, item := cache.GetModelProperty(v.ModelID, v.Field, "")
		var (
			name string
			max  float64
			min  float64
		)
		if ok {
			name = item.Name
		} else {
			fmt.Println("property is not exist", v.ModelID, v.Field)
		}
		var brand string
		thingInfo, err := cache.GetThing(v.ThingID)
		if err != nil {
			brand = thingInfo.GetThingParam("spec", "")
		}
		var airDevStatus = AirDevStatus{
			Name:      name,
			Max:       max,
			Min:       min,
			Value:     v.Value,
			Brand:     brand,
			Status:    v.Status,
			CreatTime: v.PickTime,
			Unit:      item.UnitName,
		}
		if v.Total < 9 {
			airDevStatus.Status = 8
		}

		propertys, ok := devStr[v.ModelID]
		if !ok {
			fmt.Println("no this dev")
		}
		switch v.ModelID {
		case "m_co":
			if _, ok := result["co"]; !ok {
				result["co"] = []AirDevStatus{}
			}
			for _, p := range propertys {
				if v.Field == p {
					m, ok := result["co"]
					if ok {
						result["co"] = append(m, airDevStatus)
					}
				}
			}
		case "m_nox":
			if _, ok := result["no"]; !ok {
				result["no"] = []AirDevStatus{}
			}
			if _, ok := result["no2"]; !ok {
				result["no2"] = []AirDevStatus{}
			}
			if _, ok := result["nox"]; !ok {
				result["nox"] = []AirDevStatus{}
			}
			for _, p := range propertys {
				if v.Field == p {
					no, ok := result["no"]
					no2, ok := result["no2"]
					nox, ok := result["nox"]
					if ok {
						result["no"] = append(no, airDevStatus)
						result["no2"] = append(no2, airDevStatus)
						result["nox"] = append(nox, airDevStatus)
					}
				}
			}
		case "m_so2":
			if _, ok := result["so2"]; !ok {
				result["so2"] = []AirDevStatus{}
			}
			for _, p := range propertys {
				if v.Field == p {
					m, ok := result["so2"]
					if ok {
						result["so2"] = append(m, airDevStatus)
					}
				}
			}
		case "m_o3":
			if _, ok := result["o3"]; !ok {
				result["o3"] = []AirDevStatus{}
			}
			for _, p := range propertys {
				if v.Field == p {
					m, ok := result["o3"]
					if ok {
						result["o3"] = append(m, airDevStatus)
					}
				}
			}
		case "m_pm25":
			if _, ok := result["pm2.5"]; !ok {
				result["pm2.5"] = []AirDevStatus{}
			}
			for _, p := range propertys {
				if v.Field == p {
					m, ok := result["pm2.5"]
					if ok {
						result["pm2.5"] = append(m, airDevStatus)
					}
				}
			}
		case "m_pm10":
			if _, ok := result["pm10"]; !ok {
				result["pm10"] = []AirDevStatus{}
			}
		}
		for _, p := range propertys {
			if v.Field == p {
				m, ok := result["pm10"]
				if ok {
					result["pm10"] = append(m, airDevStatus)
				}
			}
		}
	}
	for _, v := range consumerHourDev {
		v <- result
	}
}

//@id 用于注册的id
//@style 用于区分订阅的数据 5minute hour
//@return 数据通过返回通道进行传输，map中键值为项目(pm2.5,pm10,so2,o3,co,no,no2,nox)
func subscribeAirDevData(id int64, style string) chanDevDt {
	m.Lock()
	defer m.Unlock()
	switch style {
	case "5minute":
		consumer5minuteDev[id] = make(chan map[string][]AirDevStatus)
		return consumer5minuteDev[id]
	case "hour":
		consumerHourDev[id] = make(chan map[string][]AirDevStatus)
		return consumerHourDev[id]
	}
	return nil
}

func SubscribeDevByFunc(id int64, style string, run func(map[string][]AirDevStatus) error) {
	key := fmt.Sprint(id) + "dev" + "." + style
	data := subscribeAirDevData(id, style)
	ctx, cancel := context.WithCancel(context.Background())
	m.Lock()
	CronManger[key] = cancel
	m.Unlock()
	go func(c context.Context) {
		for {
			select {
			case inData := <-data:
				err := run(inData)
				if err == nil {
					fmt.Println("err:", err)
				}
				//fmt.Println("deal data end")
			case <-c.Done():
				return
			}
		}
	}(ctx)
}

func DisSubscribeAirDevData(id int64, style string) {
	key := fmt.Sprint(id) + "dev" + "." + style
	m.Lock()
	defer m.Unlock()
	if _, ok := CronManger[key]; ok {
		CronManger[key]()
	}
	switch style {
	case "5minute":
		delete(consumer5minuteDev, id)
	case "hour":
		delete(consumerHourDev, id)
	case "all":
		delete(consumer5minuteDev, id)
		delete(consumerHourDev, id)
	}
}
